package com.lgc.netdemo

import androidx.collection.SimpleArrayMap
import com.google.gson.Gson
import com.lgc.netdemo.config.CommonInterceptor
import com.lgc.netdemo.config.LocalCookieJar
import com.lgc.netdemo.config.RetryInterceptor
import okhttp3.Cache
import okhttp3.Call
import okhttp3.Callback
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import java.io.File
import java.io.IOException
import java.util.concurrent.TimeUnit

class OkHttpApi :HttpApi {
    companion object{
        private const val TAG= "OkHttpApi"
    }
//    private var baseUrl="http://api.qingyunke.com/"
//    private var baseUrl="https://www.baidu.com"
//    private var baseUrl="https://up.pec.com.cn/wechat/"
    private var baseUrl="https://api.caiyunapp.com/"
    //存储请求,用于取消
    private var callMap=SimpleArrayMap<Any,Call>()
    var maxRetry=3 //最大重试 次数
    //okhttpclient
    private val mClient=OkHttpClient.Builder()
        .callTimeout(10, TimeUnit.SECONDS)//完整请求超时时长,从发起到接收返回数据，默认值为0，不限定
        .connectTimeout(10,TimeUnit.SECONDS)//与服务器建议连接的时长，默认10s
        .readTimeout(10,TimeUnit.SECONDS)//读取服务器返回数据的时长
        .writeTimeout(10,TimeUnit.SECONDS)//向服务器写入数据的时长，默认10s
        .retryOnConnectionFailure(true)//失败重连
        .followRedirects(false)//重定向
        .cache(Cache(File("sdcard/cache","okhttp"),1024))
        .cookieJar(LocalCookieJar())
        .addNetworkInterceptor(CommonInterceptor())//公共header拦截器
            //添加网络拦截器,可以对okhttp的网络请求做拦截处理,不同于应用拦截器,这里能感知所有网络状态，比如重定向
        .addNetworkInterceptor(RetryInterceptor(maxRetry))
//        .addInterceptor(LogInterceptor())//添加拦截器
//        .cookieJar(CookieJar.NO_COOKIES)

        .build()
    override fun get(params: Map<String, String>?, path: String,/*map: Map<String, String>,*/ callback: IHttpCallback) {
        val url="$baseUrl$path"
        val urlBuilder=url.toHttpUrl().newBuilder()

        params?.forEach { entry ->urlBuilder.addEncodedQueryParameter(entry.key,entry.value) }

        val request=Request.Builder().get().url(urlBuilder.build()).tag(params)/*.headers(map)*//*.cacheControl(CacheControl.FORCE_CACHE)*/.build()
        val newCall:Call=mClient.newCall(request)
        //存储请求,用于取消
        callMap.put(request.tag(),newCall)
        newCall.enqueue(object:Callback{//异步操作
            override fun onFailure(call: Call, e: IOException) {
                e.message?.let { callback.onFailed(it) }
            }

            override fun onResponse(call: Call, response: Response) {
                callback.onSuccess(response)
            }
        })
    }

    override fun post(body: Any, path: String, callback: IHttpCallback) {
        val url="$baseUrl$path"
        val request=Request.Builder().post(Gson().toJson(body).toRequestBody("application/json".toMediaType())).tag(body).url("https://testapi.cinao5.com/accounts/login").build()
        val newCall=mClient.newCall(request)
        callMap.put(request.tag(),newCall)
        newCall.enqueue(object:Callback{
            override fun onFailure(call: Call, e: IOException) {
                callback.onFailed(e.message)
            }

            override fun onResponse(call: Call, response: Response) {
                callback.onSuccess(response)
            }

        })
    }

    /**
     * 取消请求一般用在启动请求后，要执行取消的地方调用，调用方式：HttpApi.cancelRequest(tag)
     * 或者：锁屏时，退出应用时，调用：HttpApi.cancelAllRequest()
     */

    override fun cancelRequest(tag: Any) {
       callMap.get(tag)?.cancel()
    }

    override fun cancelAllRequest() {
        for(i in 0 until callMap.size()){
            callMap.get(callMap.keyAt(i))?.cancel()
        }
    }
}